
package com.pro.common.service.file.service.unit;

import cn.hutool.core.util.ObjUtil;
import com.pro.common.api.CommonConst;
import com.pro.common.api.R;
import com.pro.common.api.common.model.BaseResult;
import com.pro.common.api.statics.user.amount.enums.EnumAmountNegativeDeal;
import com.pro.common.api.statics.user.amount.model.base.AmountEntityRecordBaseDTO;
import com.pro.common.api.statics.user.amount.model.base.AmountEntityUnitDTO;
import com.pro.common.api.user.file.model.db.UserFile;
import com.pro.common.api.user.file.model.db.UserFileNode;
import com.pro.common.api.user.file.model.request.UserFileBatchImportRequest;
import com.pro.common.api.user.file.model.request.sub.UserFileBatchImportItem;
import com.pro.common.api.user.intf.UserAmountFeignClient;
import com.pro.common.api.user.intf.UserBatchInfoFeignClient;
import com.pro.common.api.user.intf.UserFeignClient;
import com.pro.common.api.user.model.db.UserAmountRecord;
import com.pro.common.api.user.model.db.UserBatchDetail;
import com.pro.common.api.user.model.db.UserBatchInfo;
import com.pro.common.service.file.service.UserFileService;
import com.pro.common.service.file.util.sub.UserFilePathParam;
import com.pro.common.service.util.I18nUtils;
import com.pro.framework.api.enums.EnumAmountUpDown;
import com.pro.framework.api.structure.Tuple2;
import com.pro.framework.api.util.CollUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 文件聚合服务
 */
@Service
@AllArgsConstructor
public class UserFileCreateService {
    public static final String BUSINESS_TYPE = CommonConst.BusinessType.UserFile.UserFileCreateService;
    public static final String MODULE_NAME_HOME = "home";
    public static final String MODULE_NAME_HOME_TRANSLATE = "用户上传";


    private UserFileService userFileService;
    //    private UserFolderService userFolderService;
    private UserAmountFeignClient userAmountFeignClient;

    //    private UserPackageQuotaChangeRecordFeignClient userPackageQuotaChangeRecordFeignClient;
    private UserBatchInfoFeignClient userBatchInfoFeignClient;
    private UserFileStorageUnitService userFileStorageUnitService;
    private UserFeignClient<?> userFeignClient;

    // 列出所有文件和目录
    public UserFile listFileAndFolder(UserFile userFile) {
        return userFileService.getOne(userFile);
    }

    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public List<R<UserFileNode>> batchUpload(UserFileBatchImportRequest request) {
        // 如果没指定 默认都是用户自己上传 暂时统一放根目录
        String requestModuleName = ObjUtil.defaultIfNull(request.getModuleName(), MODULE_NAME_HOME);
        Long requestUserId = request.getUserId();
        Long requestParentFolderId = request.getParentFolderId();

        // 核心列表
        List<UserFileBatchImportItem> items = request.getItems();

        items.forEach(item -> {
            item.setUserId(ObjUtil.defaultIfNull(item.getUserId(), requestUserId));
            item.setParentFolderId(ObjUtil.defaultIfNull(item.getParentFolderId(), requestParentFolderId));
        });

        Set<Long> userIds = items.stream().map(UserFileBatchImportItem::getUserId).collect(Collectors.toSet());
        Map<Long, String> userLangMap = userFeignClient.idLangMap(userIds);

        // 1.保存批次
        Map<Long, List<UserFileBatchImportItem>> requestMap = CollUtils.groupBy(items, UserFileBatchImportItem::getUserId);

        List<Tuple2<UserBatchInfo, List<UserFileBatchImportItem>>> tuple2s = requestMap.entrySet().stream().map(e -> {
            Long userId = e.getKey();
            List<UserFileBatchImportItem> subItems = e.getValue();
            UserBatchInfo userBatchInfo = new UserBatchInfo(userId, BUSINESS_TYPE, subItems.stream().map(i -> {
                UserBatchDetail batchDetail = new UserBatchDetail();
                batchDetail.setRecordId(i.getFromId());
                return batchDetail;
            }).toList());
            return new Tuple2<>(userBatchInfo, subItems);
        }).toList();
        userBatchInfoFeignClient.saveBatchAndFillId(tuple2s.stream().map(Tuple2::getT1).toList());

        // 2.用户文件空间 消耗
        List<AmountEntityRecordBaseDTO> amountChangeDTOs = tuple2s.stream().map(tuple2 -> {
            UserBatchInfo batchInfo = tuple2.getT1();
            List<UserFileBatchImportItem> subItems = tuple2.getT2();
            Long allSize = subItems.stream().map(UserFileBatchImportItem::getSize).filter(Objects::nonNull).reduce(Long::sum).orElse(0L);
            return (AmountEntityRecordBaseDTO) AmountEntityRecordBaseDTO.builder()
                    .userId(batchInfo.getUserId())
                    .amountType(CommonConst.BusinessType.UserAmount.AmountType.userFileStorage)
                    .upDown(EnumAmountUpDown.up)
                    .amount(new BigDecimal(allSize))
                    .recordType(BUSINESS_TYPE)
                    .orderId(batchInfo.getId())
                    .build();
        }).toList();
        List<UserAmountRecord> records = userAmountFeignClient.change(new AmountEntityUnitDTO<>(EnumAmountNegativeDeal.failSkip, null, amountChangeDTOs, true));
        // 回填结果
        CollUtils.forEach(records, tuple2s, (record, tuple2) -> {
            UserBatchInfo batchInfo = tuple2.getT1();
            // 标记失败的
            List<UserFileBatchImportItem> subItems = tuple2.getT2();
            R<UserFileNode> result = record.getSuccessFlag() ? R.ok() : R.fail(I18nUtils.getByLang(userLangMap.get(batchInfo.getUserId()), "消耗图片空间_", record.getErrorMsg()));
            subItems.forEach(subItem -> subItem.setResult(result));
        });

        // 成功的 进入下一步
        List<UserFileBatchImportItem> itemsSuccess = items.stream().filter(i -> i.getResult().isSuccess()).toList();

        // 1.上传
        List<UserFilePathParam> fileParams = itemsSuccess.stream()
                .map(item -> {
                    // 从 URL 或本地文件名提取原始文件名
                    String originalFilename = extractFileName(item.getUrl()); // 例如 "my_photo.jpg"

                    return new UserFilePathParam(
                            requestModuleName,
                            item.getModuleNameTranslate(),
                            item.getUserId(),
                            null,
                            null,
                            originalFilename,
                            item.getUrl(),
                            item.getCreateBy()
                    );
                })
                .toList();

        // 调用批量上传
        List<R<UserFileNode>> results = userFileStorageUnitService.putObjectsCreateFileNode(fileParams);
        CollUtils.forEach(itemsSuccess, results, (item, result) -> {
            // 最后的 成功/失败结果
            item.setResult(result);
        });

        return items.stream().map(BaseResult::getResult).toList();
    }

    private String extractFileName(String url) {
        if (url == null) return null;
        int lastSlash = url.lastIndexOf('/');
        return lastSlash >= 0 ? url.substring(lastSlash + 1) : url;
    }

}
